home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / programming / source / t3dlib_src_r43.lha / readtddd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-02  |  48.1 KB  |  1,707 lines

  1. /* ReadTDDD.c - read a TDDD (Three Dimension Data Decription) file
  2.  *            - written by Glenn M. Lewis - 9/4/91
  3.  *            - Altered for Imagine 3.0 support - Rob Hounsell - Sept.94
  4.  */
  5.  
  6. static char rcs_id[] = "$Id: readtddd.c,v 1.33 1995/02/01 22:21:43 glewis Exp glewis $";
  7.  
  8. #include <stdio.h>
  9. #include <ctype.h>
  10. #include <math.h>
  11. #include "t3dlib.h"
  12. #ifdef __STDC__
  13. #include <stdlib.h>
  14. #include <strings.h>
  15. #include "readtddd_protos.h"
  16. #endif
  17. #define MAXLINE 132
  18. #ifndef PI
  19. #define PI (3.14159265)
  20. #endif
  21.  
  22. int verbose_flag=0;
  23.  
  24. static void process_DESC();
  25. static OBJECT *process_EXTR();
  26. static void process_INFO();
  27. static void process_OBJ();
  28. void insert_into_sorted_list();
  29.  
  30. /* Here are a few necessary utilities */
  31.  
  32. static void get_name(name, size, world)
  33. register char  *name;
  34. register int size;
  35. WORLD *world;
  36. {
  37.     while (size--) *name++ = fgetc(world->inp);
  38.     *name = '\0';
  39. }
  40.  
  41. static BYTE get_BYTE(world)
  42. WORLD *world;
  43. {
  44.     return((BYTE)fgetc(world->inp));
  45. }
  46.  
  47. static UBYTE get_UBYTE(world)
  48. WORLD *world;
  49. {
  50.     return((UBYTE)fgetc(world->inp));
  51. }
  52.  
  53. static WORD get_WORD(world)
  54. WORLD *world;
  55. {
  56.     WORD tmp = (WORD)get_UBYTE(world)<<8;
  57.     return((WORD)(tmp|get_UBYTE(world)));
  58. }
  59.  
  60. static UWORD get_UWORD(world)
  61. WORLD *world;
  62. {
  63.     UWORD tmp = (UWORD)get_UBYTE(world)<<8;
  64.     return((UWORD)(tmp|get_UBYTE(world)));
  65. }
  66.  
  67. static ULONG get_ULONG(world)
  68. WORLD *world;
  69. {
  70.     ULONG tmp = (ULONG)get_UWORD(world)<<16;
  71.     return(tmp|get_UWORD(world));
  72. }
  73.  
  74. static double get_FRACT(world)    /* This sets the precision to 10^(-3) */
  75. WORLD *world;
  76. {
  77.     register double whole, fract;
  78.  
  79.     whole =  (double)get_WORD(world);
  80.     fract = ((double)get_UWORD(world))/(double)65536.0;
  81.     return((double)(whole+fract));
  82. }
  83.  
  84. static void stuff_XYZ(st, world)
  85. XYZ_st *st;
  86. WORLD *world;
  87. {
  88.     st->x = get_FRACT(world);
  89.     st->y = get_FRACT(world);
  90.     st->z = get_FRACT(world);
  91. }
  92.  
  93. static void stuff_RGB(st, world)
  94. RGB_st *st;
  95. WORLD *world;
  96. {
  97.     get_UBYTE(world);    /* pad byte */
  98.     st->r = get_UBYTE(world);
  99.     st->g = get_UBYTE(world);
  100.     st->b = get_UBYTE(world);
  101. }
  102.  
  103. static void output_warning(world, area, name, size)
  104. WORLD *world;
  105. char *area, *name;
  106. ULONG size;
  107. {
  108.     ULONG i;
  109.     int j;
  110.     unsigned char tmpstr[20];
  111.  
  112.     fprintf(stderr, "WARNING: Unknown %ssub-chunk: '%s', size %lu...\n",
  113.         area, name, size);
  114.     for (i=0; i<size; i+=16) {
  115.         fprintf(stderr, "%04lx:", i);
  116.         for (j=0; j<16 && i+j<size; j++)
  117.             fprintf(stderr, " %02x", tmpstr[j] = (fgetc(world->inp)&0xff));
  118.         while (j++ < 16) fputs("   ", stderr);
  119.         fputs("    ", stderr);
  120.         /* Print out the ASCII equivalent */
  121.         for (j=0; j<16 && i+j<size; j++) {
  122.             tmpstr[j] &= 0x7F;   /* Strip off upper bit */
  123.             if (isprint(tmpstr[j]))
  124.                 fputc(tmpstr[j], stderr);
  125.             else fputc('.', stderr);
  126.         }
  127.         fputs("\n", stderr);
  128.     }
  129. }
  130.  
  131. /********************/
  132. /* The MAIN section */
  133. /********************/
  134.  
  135. int already_read_header = 0;
  136. unsigned char header_storage[13];
  137.  
  138. WORLD *read_World(file)
  139. FILE *file;
  140. {
  141.     int i;
  142.     for (i=0; i<4; i++) header_storage[i] = fgetc(file);
  143.     already_read_header = 4;
  144.     if (strncmp(header_storage, "FORM", 4)==0) {
  145.         while (i<12) header_storage[i++] = fgetc(file);
  146.         already_read_header = 12;
  147.         if (strncmp(&header_storage[8], "TDDD", 4)==0) return(read_TDDD(file));
  148. #if 0
  149.         if (strncmp(&header_storage[8], "LWOB", 4)==0) return(read_LWOB(file));
  150. #endif
  151.         if (strncmp(&header_storage[8], "ISTG", 4)==0) return(read_ISTG(file));
  152.         /* BAD IFF */
  153.         header_storage[12] = 0;
  154.         fprintf(stderr, "ERROR! Unknown FORM: '%s'\n", &header_storage[8]);
  155.         return(0);
  156.     } else {
  157.         return(read_TTDDD(file));
  158.     }
  159. }
  160.  
  161. WORLD *read_TDDD(file)
  162. FILE *file;
  163. {
  164.     register ULONG i, len, size;
  165.     WORLD *world;
  166.     char name[5];
  167.  
  168.     if (!file) return(0L);    /* File not open */
  169.  
  170.     if (!(world = (WORLD*)malloc(sizeof(WORLD)))) { OUT_MEM("WORLD"); }
  171.     bzero((char*)world, sizeof(WORLD));
  172.     world->inp = file;
  173.  
  174.     if (!already_read_header) {
  175.         /* Parse the IFF TDDD file */
  176.         get_name(name, 4, world);
  177.         if (strcmp(name, "FORM") != 0) {
  178.             fprintf(stderr, "ERROR: Input is not an IFF file.\n"); exit(-1); }
  179.         if (!(len = get_ULONG(world))) {
  180.             fprintf(stderr, "ERROR: Bad FORM length in IFF file.\n"); exit(-1); }
  181.         get_name(name, 4, world);
  182.         if (strcmp(name, "TDDD") != 0) {
  183.             fprintf(stderr, "ERROR: IFF file is not a TDDD file.\n"); exit(-1); }
  184.     } else {
  185.         len =    (header_storage[4]<<24) | (header_storage[5]<<16) |
  186.                 (header_storage[6]<< 8) | (header_storage[7]    );
  187.         already_read_header = 0;
  188.     }
  189.     len -= 4;
  190.  
  191. /* Here is the main loop: */
  192.     while (len>0) {
  193.         get_name(name, 4, world);
  194.         size = get_ULONG(world);
  195.         len -= 8;
  196.         if (strcmp(name, "INFO")==0) process_INFO(size, world);
  197.         else
  198.         if (strcmp(name, "OBJ ")==0) process_OBJ(size, world);
  199.         else {
  200.             if (verbose_flag) output_warning(world, "", name, size);
  201.             else {
  202.                 for (i=size; i--; ) fgetc(world->inp);    /* Skip this section */
  203.             }
  204.         }
  205.         if (size&1) { fgetc(world->inp); len--; }    /* Skip odd byte */
  206.         len -= size;
  207.     }
  208.  
  209. /* All done. */
  210.     return(world);
  211. }
  212.  
  213. static void process_INFO(len, world)
  214. register ULONG len;
  215. WORLD *world;
  216. {
  217.     register INFO *info;
  218.     register ULONG i, size;
  219.     char name[5];
  220.  
  221.     if (world->info) {
  222.         fputs("ERROR: More than one INFO chunk!\n", stderr); exit(-1); }
  223.     if (!(info = world->info = (INFO*)malloc(sizeof(INFO)))) { OUT_MEM("INFO"); }
  224.     bzero((char*)world->info, sizeof(INFO));
  225.  
  226.     if (verbose_flag>1) fprintf(stderr, "INFO chunk.\n");
  227.     while (len>0) {
  228.         get_name(name, 4, world);
  229.         size = get_ULONG(world);
  230.         len -= 8;
  231.         if (verbose_flag>1) fprintf(stderr, "%s chunk.\n", name);
  232.         if (strcmp(name, "BRSH")==0) {
  233.             i = get_UWORD(world);
  234.             if (i<0 || i>7) { i=0; fputs("BRSH error.\n", stderr); }
  235.             get_name(info->brsh[i], 80, world);
  236.         } else
  237.         if (strcmp(name, "STNC")==0) {
  238.             i = get_UWORD(world);
  239.             if (i<0 || i>7) { i=0; fputs("STNC error.\n", stderr); }
  240.             get_name(info->stnc[i], 80, world);
  241.         } else
  242.         if (strcmp(name, "TXTR")==0) {
  243.             i = get_UWORD(world);
  244.             if (i<0 || i>7) { i=0; fputs("TXTR error.\n", stderr); }
  245.             get_name(info->txtr[i], 80, world);
  246.         } else
  247.         if (strcmp(name, "OBSV")==0) {
  248.             if (!info->obsv) info->obsv=(OBSV*)malloc(sizeof(OBSV));
  249.             if (!info->obsv) { OUT_MEM("OBSV"); }
  250.             stuff_XYZ(&info->obsv->came, world);
  251.             stuff_XYZ(&info->obsv->rota, world);
  252.             info->obsv->foca = get_FRACT(world);
  253.         } else
  254.         if (strcmp(name, "OTRK")==0) {
  255.             get_name(info->otrk, 18, world);
  256.         } else
  257.         if (strcmp(name, "OSTR")==0) {
  258.             if (!info->ostr) info->ostr=(STRY*)malloc(sizeof(STRY));
  259.             if (!info->ostr) { OUT_MEM("OSTR"); }
  260.             get_name(info->ostr->path, 18, world);
  261.             stuff_XYZ(&info->ostr->tran, world);
  262.             stuff_XYZ(&info->ostr->rota, world);
  263.             stuff_XYZ(&info->ostr->scal, world);
  264.             info->ostr->info = get_UWORD(world);
  265.         } else
  266.         if (strcmp(name, "FADE")==0) {
  267.             if (!info->fade) info->fade=(FADE*)malloc(sizeof(FADE));
  268.             if (!info->fade) { OUT_MEM("FADE"); }
  269.             info->fade->at = get_FRACT(world);
  270.             info->fade->by = get_FRACT(world);
  271.             stuff_RGB(&info->fade->to, world);
  272.         } else
  273.         if (strcmp(name, "SKYC")==0) {
  274.             if (!info->skyc) info->skyc=(SKYC*)malloc(sizeof(SKYC));
  275.             if (!info->skyc) { OUT_MEM("SKYC"); }
  276.             stuff_RGB(&info->skyc->hori, world);
  277.             stuff_RGB(&info->skyc->zeni, world);
  278.         } else
  279.         if (strcmp(name, "AMBI")==0) {
  280.             if (!info->ambi) info->ambi=(RGB_st*)malloc(sizeof(RGB_st));
  281.             if (!info->ambi) { OUT_MEM("AMBI"); }
  282.             stuff_RGB(info->ambi, world);
  283.         } else
  284.         if (strcmp(name, "GLB0")==0) {
  285.             if (!info->glb0) info->glb0=(BYTE*)malloc(8*sizeof(BYTE));
  286.             if (!info->glb0) { OUT_MEM("GLB0"); }
  287.             for (i=0; i<8; i++)
  288.                 info->glb0[i] = get_UBYTE(world);
  289.         } else {
  290.             if (verbose_flag) output_warning(world, "INFO ", name, size);
  291.             else {
  292.                 for (i=size; i--; ) fgetc(world->inp);    /* Skip this section */
  293.             }
  294.         }
  295.         if (size&1) { fgetc(world->inp); len--; }    /* Skip odd byte */
  296.         len -= size;
  297.     }
  298. }
  299.  
  300. static void process_OBJ(len, world)
  301. register ULONG len;
  302. WORLD *world;
  303. {
  304.     register ULONG i, size;
  305.     register OBJECT *p;
  306.     char name[5];
  307.     int depth=0;
  308.  
  309.     if (verbose_flag>1) fprintf(stderr, "OBJ chunk.\n");
  310.     while (len>0) {
  311.         get_name(name, 4, world);
  312.         size = get_ULONG(world);
  313.         len -= 8;
  314.         if (verbose_flag>1) fprintf(stderr, "%s chunk.\n", name);
  315.         if (strcmp(name, "EXTR")==0) {
  316.             p = process_EXTR(size, create_object(), world);
  317.             if (world->curobj) {
  318.                 world->curobj->next = p;
  319.                 p->parent = world->curobj->parent;
  320.             } else {
  321.                 world->object = p;
  322.                 p->parent = 0;
  323.             }
  324.             world->curobj = p;
  325.         } else if (strcmp(name, "DESC")==0) {
  326.             p = create_object();
  327.             if (world->num_DESC > world->num_TOBJ+depth) {  /* This is a child */
  328.                 depth++;    /* Down one in the hierarchy */
  329.                 world->curobj->child = p;
  330.                 p->parent = world->curobj;
  331.             } else {
  332.                 if (world->curobj) {
  333.                     world->curobj->next = p;
  334.                     p->parent = world->curobj->parent;
  335.                 } else {
  336.                     world->object = p;
  337.                     p->parent = 0;
  338.                 }
  339.             }
  340.             world->curobj = p;
  341.             process_DESC(size, &p->desc, world);
  342.         } else if (strcmp(name, "TOBJ")==0) {
  343.             world->num_TOBJ++;
  344.             if (world->num_TOBJ > world->num_DESC) {
  345.                 fprintf(stderr, "Warning: TOBJ without DESC.  Ignored.\n");
  346.             }
  347.             if (world->num_TOBJ+depth > world->num_DESC) {  /* Up a level */
  348.                 depth--;
  349.                 world->curobj=world->curobj->parent;
  350.             }
  351.         } else {
  352.             if (verbose_flag) output_warning(world, "OBJ ", name, size);
  353.             else {
  354.                 for (i=size; i--; ) fgetc(world->inp);    /* Skip this section */
  355.             }
  356.         }
  357.         if (size&1) { fgetc(world->inp); len--; }    /* Skip odd byte */
  358.         len -= size;
  359.     }
  360. }
  361.  
  362. OBJECT *load_external_object(filename, mtrx)
  363. char *filename;
  364. MTRX *mtrx;
  365. {
  366.     WORLD *new;
  367.     FILE *newinp;
  368.     register OBJECT *p;
  369.  
  370.     /* Now, load in the external object */
  371. TRY_EXTR_AGAIN:
  372.     if (!(newinp=fopen(filename, "r"))) {
  373.         fprintf(stderr, "Can't load in EXTR object: '%s'.\n",
  374.             filename);
  375.         fprintf(stderr, "Enter filneame (or CR to abort): "); fflush(stderr);
  376.         fgets(filename, 512, stdin);
  377.         if (!filename[0] || filename[0]=='\n') return(0L);
  378.         goto TRY_EXTR_AGAIN;
  379.     }
  380.     new = read_World(newinp);
  381.     fclose(newinp);
  382.     /* scale, rotate, and translate new object hierarchy */
  383.     for (p=new->object; p; p=p->next)
  384.         move_extr(p, mtrx);
  385.  
  386.     p = new->object;
  387.     free((char*)new);
  388.     return(p);
  389. }
  390.  
  391. static OBJECT *process_EXTR(len, obj, world)
  392. register ULONG len;
  393. OBJECT *obj;
  394. WORLD *world;
  395. {
  396.     register ULONG i, size;
  397.     register EXTR *extr;
  398.     char name[5];
  399.     MTRX *mtrx;
  400.  
  401.     if (!(extr = obj->extr = (EXTR*)malloc(sizeof(EXTR))))
  402.         { OUT_MEM("EXTR"); }
  403.     bzero((char*)extr, sizeof(EXTR));
  404.     mtrx = &extr->mtrx;
  405.     /* Initialize structure */
  406.     mtrx->tran.x  = mtrx->tran.y  = mtrx->tran.z  = 0.0;
  407.     mtrx->scal.x  = mtrx->scal.y  = mtrx->scal.z  = 1.0;
  408.     mtrx->rota1.y = mtrx->rota1.z = 0.0;
  409.     mtrx->rota2.x = mtrx->rota2.z = 0.0;
  410.     mtrx->rota3.x = mtrx->rota3.y = 0.0;
  411.     mtrx->rota1.x = mtrx->rota2.y = mtrx->rota3.z = 1.0;
  412.  
  413.     if (verbose_flag>1) fprintf(stderr, "EXTR chunk.\n");
  414.     while (len>0) {
  415.         get_name(name, 4, world);
  416.         size = get_ULONG(world);
  417.         len -= 8;
  418.         if (verbose_flag>1) fprintf(stderr, "%s chunk.\n", name);
  419.         if (strcmp(name, "MTRX")==0) {
  420.             stuff_XYZ(&mtrx->tran, world);
  421.             stuff_XYZ(&mtrx->scal, world);
  422.             stuff_XYZ(&mtrx->rota1, world);
  423.             stuff_XYZ(&mtrx->rota2, world);
  424.             stuff_XYZ(&mtrx->rota3, world);
  425.         } else
  426.         if (strcmp(name, "LOAD")==0) {
  427.             get_name(extr->filename, 80, world);
  428.         } else {
  429.             if (verbose_flag) output_warning(world, "EXTR ", name, size);
  430.             else {
  431.                 for (i=size; i--; ) fgetc(world->inp);    /* Skip this section */
  432.             }
  433.         }
  434.         if (size&1) { fgetc(world->inp); len--; }    /* Skip odd byte */
  435.         len -= size;
  436.     }
  437.  
  438.     /* Free up unused memory */
  439.     free((char*)obj->extr);
  440.     free((char*)obj);
  441.  
  442.     obj = load_external_object(extr->filename, mtrx);
  443.     return(obj);
  444. }
  445.  
  446. static UBYTE defclst[3], defrlst[3], deftlst[3], defspc1[3];
  447.  
  448. static void malloc_arrays(i, desc)
  449. register int i;
  450. register DESC *desc;
  451. {
  452.     if (!desc->fcount) {
  453.         desc->fcount = i;
  454. if (!(desc->face=(UWORD*)malloc(3*desc->fcount*sizeof(UWORD))))OUT_MEM((char*)0);
  455. if (!(desc->clst=(UBYTE*)malloc(3*desc->fcount*sizeof(UBYTE))))OUT_MEM((char*)0);
  456. if (!(desc->rlst=(UBYTE*)malloc(3*desc->fcount*sizeof(UBYTE))))OUT_MEM((char*)0);
  457. if (!(desc->tlst=(UBYTE*)malloc(3*desc->fcount*sizeof(UBYTE))))OUT_MEM((char*)0);
  458.         /* Initialize arrays */
  459.         for (i=0; i<3*desc->fcount; i+=3) {
  460.             desc->face[i]   = desc->face[i+1] = desc->face[i+2] = 0;
  461.             desc->clst[i]   = defclst[0];
  462.             desc->clst[i+1] = defclst[1];
  463.             desc->clst[i+2] = defclst[2];
  464.             desc->rlst[i]   = defrlst[0];
  465.             desc->rlst[i+1] = defrlst[1];
  466.             desc->rlst[i+2] = defrlst[2];
  467.             desc->tlst[i]   = deftlst[0];
  468.             desc->tlst[i+1] = deftlst[1];
  469.             desc->tlst[i+2] = deftlst[2];
  470.         }
  471.     } else if (i != desc->fcount) {
  472.         fprintf(stderr, "ERROR: FACE and [C|R|T]LST 'Count' values inconsistant.\n");
  473.         OUT_MEM((char*)0);
  474.     }
  475. }
  476.  
  477. static void process_DESC(len, orig, world)
  478. register ULONG len;
  479. DESC **orig;
  480. WORLD *world;
  481. {
  482.     register ULONG size;
  483.     register DESC *desc;
  484.     register int i, j;
  485.     FGRP *fgrp;
  486.     char name[5];
  487.     ULONG ccsize;
  488.  
  489.     if (!(desc = *orig = (DESC*)malloc(sizeof(DESC))))
  490.         { OUT_MEM("DESC"); }
  491.     bzero((char*)desc, sizeof(DESC));
  492.  
  493.     /* Set up defaults: */
  494.     defclst[0] = defclst[1] = defclst[2] = 240; /* TS default */
  495.     defrlst[0] = defrlst[1] = defrlst[2] = 0;
  496.     deftlst[0] = deftlst[1] = deftlst[2] = 0;
  497.     defspc1[0] = defspc1[1] = defspc1[2] = 0;
  498.  
  499.     world->num_DESC++;
  500.  
  501.     if (verbose_flag>1) fprintf(stderr, "DESC chunk.\n");
  502.     while (len>0) {
  503.         get_name(name, 4, world);
  504.         size = get_ULONG(world);
  505.         len -= 8;
  506.         if (verbose_flag>1) fprintf(stderr, "%s chunk.\n", name);
  507.         if (strcmp(name, "NAME")==0) {
  508.             get_name(desc->name, 18, world);
  509.         } else
  510.         if (strcmp(name, "SHAP")==0) {
  511.             if (!desc->shap) {
  512.                 if (!(desc->shap=(WORD*)malloc(2*sizeof(WORD))))
  513.                     { OUT_MEM("SHAP"); }
  514.                 desc->shap[0] = 2;  /* TS defaults */
  515.                 desc->shap[1] = 0;
  516.             }
  517.             desc->shap[0] = get_UWORD(world);
  518.             desc->shap[1] = get_UWORD(world);
  519.         } else
  520.         if (strcmp(name, "POSI")==0) {
  521.             if (!desc->posi) {
  522.                 if (!(desc->posi=(XYZ_st*)malloc(sizeof(XYZ_st))))
  523.                     { OUT_MEM("POSI"); }
  524.             }
  525.             stuff_XYZ(desc->posi, world);
  526.         } else
  527.         if (strcmp(name, "AXIS")==0) {
  528.             if (!desc->axis) {
  529.                 if (!(desc->axis=(AXIS*)malloc(sizeof(AXIS))))
  530.                     { OUT_MEM("AXIS"); }
  531.                 bzero((char*)desc->axis, sizeof(AXIS));
  532.                 desc->axis->xaxi.x = 1;
  533.                 desc->axis->yaxi.y = 1;
  534.                 desc->axis->zaxi.z = 1;
  535.             }
  536.             stuff_XYZ(&desc->axis->xaxi, world);
  537.             stuff_XYZ(&desc->axis->yaxi, world);
  538.             stuff_XYZ(&desc->axis->zaxi, world);
  539.         } else
  540.         if (strcmp(name, "SIZE")==0) {
  541.             if (!desc->size) {
  542.                 if (!(desc->size=(XYZ_st*)malloc(sizeof(XYZ_st))))
  543.                     { OUT_MEM("SIZE"); }
  544.             }
  545.             stuff_XYZ(desc->size, world);
  546.         } else
  547.         if (strcmp(name, "PNTS")==0) {
  548.             i = desc->pcount = get_UWORD(world);    /* Number of points */
  549.             if (!(desc->pnts = (XYZ_st*)malloc(desc->pcount*sizeof(XYZ_st))))
  550.                 OUT_MEM("PNTS");
  551.             for (j=0; j<i; j++)
  552.                 { stuff_XYZ(&desc->pnts[j], world); }
  553.         } else
  554.         if (strcmp(name, "EDGE")==0) {
  555.             i = desc->ecount = get_UWORD(world);    /* Number of edges */
  556.             if (!(desc->edge = (UWORD*)malloc(2*desc->ecount*sizeof(UWORD))))
  557.                 OUT_MEM("EDGE");
  558.             for (j=0; j<2*i; j++)
  559.                 { desc->edge[j] = get_UWORD(world); }
  560.         } else
  561.         if (strcmp(name, "EFLG")==0) {        /* An undocumented chunk */
  562.             if (!(desc->eflg = (EFLG*)malloc(sizeof(EFLG))))
  563.                 OUT_MEM("EFLG");
  564.             i = desc->eflg->num = get_UWORD(world);    /* Number of edge flags */
  565.             if (!(desc->eflg->eflg=(UBYTE*)malloc(desc->eflg->num*sizeof(UBYTE))))
  566.                 OUT_MEM("EFLG");
  567.             for (j=0; j<i; j++)
  568.                 { desc->eflg->eflg[j] = get_UBYTE(world); }
  569.         } else
  570.         if (strcmp(name, "FACE")==0) {
  571.             i = get_UWORD(world);                /* Number of faces */
  572.             malloc_arrays(i, desc);
  573.             for (j=0; j<i; j++) {
  574.                 desc->face[3*j]   = get_UWORD(world);
  575.                 desc->face[3*j+1] = get_UWORD(world);
  576.                 desc->face[3*j+2] = get_UWORD(world);
  577.             }
  578.         } else
  579.         if (strcmp(name, "BRS3")==0) {
  580.             fprintf(stderr, "BRS3:\n");
  581.             for (i=0; i<21; i++) {
  582.                 fprintf(stderr, "%.12g\n", get_FRACT(world));
  583.             }
  584.             get_UWORD(world);
  585.             i = get_UBYTE(world);
  586.             while (i--) {
  587.                 fputc(get_UBYTE(world), stderr);
  588.             }
  589.         } else
  590.         if (strcmp(name, "TXT2")==0) {
  591.             for (i=0; i<4 && desc->txt2[i]; i++) ;
  592.             if (i==4) {        /* ERROR! */
  593.                 fprintf(stderr, "WARNING! More than 4 TXT2 chunks!\n");
  594.                 i--;
  595.             }
  596.             if (!(desc->txt2[i] = (TXT2*)malloc(sizeof(TXT2)))) OUT_MEM("TXT2");
  597.             desc->txt2[i]->Flags = get_UWORD(world);
  598.             ccsize = 2;
  599.             stuff_XYZ(&desc->txt2[i]->TAxis.tran, world);
  600.             stuff_XYZ(&desc->txt2[i]->TAxis.rota1, world);
  601.             stuff_XYZ(&desc->txt2[i]->TAxis.rota2, world);
  602.             stuff_XYZ(&desc->txt2[i]->TAxis.rota3, world);
  603.             stuff_XYZ(&desc->txt2[i]->TAxis.scal, world);
  604.             ccsize = ccsize + 60;
  605.             for (j = 0; j < 16; j++) desc->txt2[i]->Params[j] = get_FRACT(world);
  606.             ccsize = ccsize + 64;
  607.             for (j = 0; j < 16; j++) desc->txt2[i]->PFlags[j] = get_UBYTE(world);
  608.             ccsize = ccsize + 16;
  609.             ccsize = ccsize + 17;
  610.             get_name(desc->txt2[i]->SubName, 17, world);
  611.             j = get_UWORD(world);
  612.             ccsize = ccsize + 2 + j;
  613.             desc->txt2[i]->Length = j;
  614.             get_name(desc->txt2[i]->Name, j, world);
  615.             for (j=ccsize; j < size; j++) get_UBYTE(world);
  616.         } else
  617. #if 0
  618.         if (strcmp(name, "FOR2")==0) {        /* Another undocumented chunk */
  619.             newsize = size;
  620.             i = get_UWORD(world);    /* NumC */
  621.             newsize -= 2;
  622.             NumC = i;
  623.             fprintf(stderr, "Encountered 'FOR2' chunk...size=%lu\n  NumC=%u\n", size, i);
  624.             i = get_UWORD(world);    /* NumF */
  625.             newsize -= 2;
  626.             NumF = i;
  627.             fprintf(stderr, "  NumF=%u\n", i);
  628.             i = get_UWORD(world);    /* Flags */
  629.             newsize -= 2;
  630.             fprintf(stderr, "  Flags=%u\n", i);
  631.             i = get_UWORD(world);    /* pad */
  632.             newsize -= 2;
  633.             fprintf(stderr, "  pad=%u\n", i);
  634.             for (j=0; j<9; j++) fprintf(stderr, "  MTRX[%d]=%.12g\n", j, get_FRACT(world));
  635.             newsize -= 36;
  636.             fprintf(stderr, "  ShiftX=%.12g ", get_FRACT(world));
  637.             fprintf(stderr, "ShiftY=%.12g ", get_FRACT(world));
  638.             fprintf(stderr, "ShiftZ=%.12g\n", get_FRACT(world));
  639.             newsize -= 12;
  640.             for (j=0; j<NumC+4*NumF; j++) {
  641.                 fprintf(stderr, "  Point[%d]: X=%.12g ", j, get_FRACT(world));
  642.                 fprintf(stderr, "Y=%.12g ", get_FRACT(world));
  643.                 fprintf(stderr, "Z=%.12g\n", get_FRACT(world));
  644.                 newsize -= 12;
  645.             }
  646.             output_warning(world, "DESC ", "FOR2", newsize);
  647.         } else
  648. #endif
  649.         if (strcmp(name, "FGRP")==0) {        /* Another undocumented chunk */
  650.             if (!(fgrp = (FGRP*)malloc(sizeof(FGRP))))
  651.                 OUT_MEM("FGRP");
  652.             i = fgrp->num = get_UWORD(world);    /* Number of faces in group */
  653.             if (!(fgrp->face = (UWORD*)malloc(i*sizeof(UWORD))))
  654.                 OUT_MEM("FGRP");
  655.             get_name(fgrp->name, 18, world);
  656.             for (j=0; j<i; j++)
  657.                 fgrp->face[j] = get_UWORD(world);
  658.             /* Link this new FGRP into list */
  659.             fgrp->next = desc->fgrp;
  660.             desc->fgrp = fgrp;
  661.         } else
  662.         if (strcmp(name, "COLR")==0) {
  663.             if (!desc->colr) {
  664.                 if (!(desc->colr = (RGB_st*)malloc(sizeof(RGB_st))))
  665.                     { OUT_MEM("COLR"); }
  666.             }
  667.             stuff_RGB((RGB_st*)&defclst[0], world);
  668.             desc->colr->r = defclst[0];
  669.             desc->colr->g = defclst[1];
  670.             desc->colr->b = defclst[2];
  671.         } else
  672.         if (strcmp(name, "REFL")==0) {
  673.             if (!desc->refl) {
  674.                 if (!(desc->refl = (RGB_st*)malloc(sizeof(RGB_st))))
  675.                     { OUT_MEM("REFL"); }
  676.             }
  677.             stuff_RGB((RGB_st*)&defrlst[0], world);
  678.             desc->refl->r = defrlst[0];
  679.             desc->refl->g = defrlst[1];
  680.             desc->refl->b = defrlst[2];
  681.         } else
  682.         if (strcmp(name, "TRAN")==0) {
  683.             if (!desc->tran) {
  684.                 if (!(desc->tran = (RGB_st*)malloc(sizeof(RGB_st))))
  685.                     { OUT_MEM("TRAN"); }
  686.             }
  687.             stuff_RGB((RGB_st*)&deftlst[0], world);
  688.             desc->tran->r = deftlst[0];
  689.             desc->tran->g = deftlst[1];
  690.             desc->tran->b = deftlst[2];
  691.         } else
  692.         if (strcmp(name, "SPC1")==0) {
  693.             if (!desc->spc1) {
  694.                 if (!(desc->spc1 = (RGB_st*)malloc(sizeof(RGB_st))))
  695.                     { OUT_MEM("SPC1"); }
  696.             }
  697.             stuff_RGB((RGB_st*)&defspc1[0], world);
  698.             desc->spc1->r = defspc1[0];
  699.             desc->spc1->g = defspc1[1];
  700.             desc->spc1->b = defspc1[2];
  701.         } else
  702.         if (strcmp(name, "CLST")==0) {
  703.             i = get_UWORD(world);        /* Number of faces */
  704.             malloc_arrays(i, desc);
  705.             for (j=0; j<i; j++) {
  706.                 desc->clst[3*j+0] = get_UBYTE(world);
  707.                 desc->clst[3*j+1] = get_UBYTE(world);
  708.                 desc->clst[3*j+2] = get_UBYTE(world);
  709.             }
  710.         } else
  711.         if (strcmp(name, "RLST")==0) {
  712.             i = get_UWORD(world);        /* Number of faces */
  713.             malloc_arrays(i, desc);
  714.             for (j=0; j<i; j++) {
  715.                 desc->rlst[3*j+0] = get_UBYTE(world);
  716.                 desc->rlst[3*j+1] = get_UBYTE(world);
  717.                 desc->rlst[3*j+2] = get_UBYTE(world);
  718.             }
  719.         } else
  720.         if (strcmp(name, "TLST")==0) {
  721.             i = get_UWORD(world);        /* Number of faces */
  722.             malloc_arrays(i, desc);
  723.             for (j=0; j<i; j++) {
  724.                 desc->tlst[3*j+0] = get_UBYTE(world);
  725.                 desc->tlst[3*j+1] = get_UBYTE(world);
  726.                 desc->tlst[3*j+2] = get_UBYTE(world);
  727.             }
  728.         } else
  729.         if (strcmp(name, "TPAR")==0) {
  730.             if (!desc->tpar) {
  731.                 if (!(desc->tpar=(double*)malloc(16*sizeof(double))))
  732.                     { OUT_MEM("TPAR"); }
  733.                 bzero((char*)desc->tpar, 16*sizeof(double));
  734.             }
  735.             for (i=0; i<16; i++)
  736.                 desc->tpar[i] = get_FRACT(world);
  737.         } else
  738.         if (strcmp(name, "SURF")==0) {
  739.             if (!desc->surf) {
  740.                 if (!(desc->surf=(UBYTE*)malloc(5*sizeof(UBYTE))))
  741.                     { OUT_MEM("SURF"); }
  742.                 bzero((char*)desc->surf, 5*sizeof(UBYTE));
  743.             }
  744.             for (i=0; i<5; i++)
  745.                 desc->surf[i] = get_BYTE(world);
  746.         } else
  747.         if (strcmp(name, "MTTR")==0) {
  748.             if (!desc->mttr) {
  749.                 if (!(desc->mttr=(MTTR*)malloc(sizeof(MTTR))))
  750.                     { OUT_MEM("MTTR"); }
  751.                 bzero((char*)desc->mttr, sizeof(MTTR));
  752.             }
  753.             desc->mttr->type = get_UBYTE(world);
  754.             desc->mttr->indx = (get_UBYTE(world)/100.0)+1.0;
  755.         } else
  756.         if (strcmp(name, "SPEC")==0) {
  757.             if (!desc->spec) {
  758.                 if (!(desc->spec=(UBYTE*)malloc(2*sizeof(UBYTE))))
  759.                     { OUT_MEM("SPEC"); }
  760.                 bzero((char*)desc->spec, 2*sizeof(UBYTE));
  761.             }
  762.             desc->spec[0] = get_UBYTE(world);
  763.             desc->spec[1] = get_UBYTE(world);
  764.         } else
  765.         if (strcmp(name, "PRP0")==0) {
  766.             if (!desc->prp0) {
  767.                 if (!(desc->prp0=(UBYTE*)malloc(6*sizeof(UBYTE))))
  768.                     { OUT_MEM("PRP0"); }
  769.                 bzero((char*)desc->prp0, 6*sizeof(UBYTE));
  770.             }
  771.             for (i=0; i<6; i++)
  772.                 desc->prp0[i] = get_UBYTE(world);
  773.         } else
  774.         if (strcmp(name, "PRP1")==0) {
  775.             if (!desc->prp1) {
  776.                 if (!(desc->prp1=(UBYTE*)malloc(8*sizeof(UBYTE))))
  777.                     { OUT_MEM("PRP1"); }
  778.                 bzero((char*)desc->prp1, 8*sizeof(UBYTE));
  779.             }
  780.             for (i=0; i<8; i++)
  781.                 desc->prp1[i] = get_UBYTE(world);
  782.         } else
  783.         if (strcmp(name, "INTS")==0) {
  784.             if (!desc->ints) {
  785.                 if (!(desc->ints=(double*)malloc(sizeof(double))))
  786.                     { OUT_MEM("INTS"); }
  787.             }
  788.             *desc->ints = get_FRACT(world);
  789.         } else
  790.         if (strcmp(name, "INT1")==0) {
  791.             if (!desc->int1) desc->int1=(XYZ_st*)malloc(sizeof(XYZ_st));
  792.             if (!desc->int1) { OUT_MEM("INT1"); }
  793.             stuff_XYZ(desc->int1, world);
  794.         } else
  795.         if (strcmp(name, "STRY")==0) {
  796.             get_name(desc->stry->path, 18, world);
  797.             stuff_XYZ(&desc->stry->tran, world);
  798.             stuff_XYZ(&desc->stry->rota, world);
  799.             stuff_XYZ(&desc->stry->scal, world);
  800.             desc->stry->info = get_UWORD(world);
  801.         } else {
  802.             if (verbose_flag) output_warning(world, "DESC ", name, size);
  803.             else {
  804.                 for (i=size; i--; ) fgetc(world->inp);    /* Skip this section */
  805.             }
  806.         }
  807.         if (size&1) { fgetc(world->inp); len--; }    /* Skip odd byte */
  808.         len -= size;
  809.     }
  810. }
  811.  
  812. /* readistg.c - read an Imagine Stage file
  813.  *            - written by Glenn M. Lewis - 8/11/92
  814.  *            - Imagine3 update by Rob Hounsell - Sept 94
  815.  */
  816.  
  817. static void process_OSZ2();
  818. static void process_OSIZ();
  819. static void process_POS2();
  820. static void process_POSN();
  821. static void process_ALN2();
  822. static void process_ALGN();
  823. static void process_PALN();
  824. static void process_TALN();
  825. static void process_ASSC();
  826. static void process_HING();
  827. static void process_LYR0();
  828. static void process_PTH2();
  829. static void process_GLB3();
  830. static void process_GLB2();
  831. static void process_AXIS();
  832. static void process_LIT2();
  833. static void process_LITE();
  834. static void process_FIL3();
  835. static void process_FILE();
  836. static void process_SPFX();
  837. static void process_SOBJ();
  838.  
  839. WORLD *read_ISTG(file)
  840. FILE *file;
  841. {
  842.     register ULONG i, len, size;
  843.     WORLD *world;
  844.     char name[5];
  845.  
  846.     if (!file) return(0L);    /* File not open */
  847.  
  848.     if (!(world = (WORLD*)malloc(sizeof(WORLD)))) { OUT_MEM("WORLD"); }
  849.     bzero((char*)world, sizeof(WORLD));
  850.     world->inp = file;
  851.  
  852.     if (!already_read_header) {
  853.         /* Parse the IFF ISTG file */
  854.         get_name(name, 4, world);
  855.         if (strcmp(name, "FORM") != 0) {
  856.             fprintf(stderr, "ERROR: Input is not an IFF file.\n"); exit(-1); }
  857.         if (!(len = get_ULONG(world))) {
  858.             fprintf(stderr, "ERROR: Bad FORM length in IFF file.\n"); exit(-1); }
  859.         get_name(name, 4, world);
  860.         if (strcmp(name, "ISTG") != 0) {
  861.             fprintf(stderr, "ERROR: IFF file is not a ISTG file.\n"); exit(-1); }
  862.     } else {
  863.         len =    (header_storage[4]<<24) | (header_storage[5]<<16) |
  864.                 (header_storage[6]<< 8) | (header_storage[7]    );
  865.         already_read_header = 0;
  866.     }
  867.     len -= 4;
  868.  
  869.     /* Allocate the ISTG structure */
  870.     if (!(world->istg = (ISTG*)malloc(sizeof(ISTG)))) { OUT_MEM("ISTG"); }
  871.     bzero((char*)world->istg, sizeof(ISTG));
  872.  
  873. /* Here is the main loop: */
  874.     while (len>0) {
  875.         get_name(name, 4, world);
  876.         size = get_ULONG(world);
  877.         len -= 8;
  878.         if (strcmp(name, "MAXF")==0) world->istg->maxf = get_UWORD(world);
  879.         else
  880.         if (strcmp(name, "LOOP")==0) world->istg->loop = get_UWORD(world);
  881.         else
  882.         if (strcmp(name, "SOBJ")==0) process_SOBJ(size, world);
  883.         else {
  884.             if (verbose_flag) output_warning(world, "ISTG ", name, size);
  885.             else {
  886.                 for (i=size; i--; ) fgetc(world->inp);    /* Skip this section */
  887.             }
  888.         }
  889.         if (size&1) { fgetc(world->inp); len--; }    /* Skip odd byte */
  890.         len -= size;
  891.     }
  892.  
  893. /* All done. */
  894.     return(world);
  895. }
  896.  
  897. SOBJ *add_SOBJ(istg)    /* to tail of ISTG's SOBJ list */
  898. ISTG *istg;
  899. {
  900.     SOBJ *new;
  901.  
  902.     if (!(new = (SOBJ*)malloc(sizeof(SOBJ)))) OUT_MEM("SOBJ");
  903.     bzero((char*)new, sizeof(SOBJ));
  904.  
  905.     if (!istg->head) {
  906.         istg->head = istg->tail = new;
  907.         return(new);
  908.     }
  909.     /* Add this SOBJ to the tail */
  910.     new->prev = istg->tail;
  911.     istg->tail->next = new;
  912.     istg->tail = new;
  913.     return(new);
  914. }
  915.  
  916. static void process_SOBJ(len, world)
  917. register ULONG len;
  918. WORLD *world;
  919. {
  920.     register ULONG i, size;
  921.     char name[5];
  922.     SOBJ *sobj;
  923.  
  924.     if (verbose_flag>1) fprintf(stderr, "SOBJ chunk.\n");
  925.     /* Add another SOBJ to the current ISTG list */
  926.     sobj = add_SOBJ(world->istg);
  927.     while (len>0) {
  928.         get_name(name, 4, world);
  929.         size = get_ULONG(world);
  930.         len -= 8;
  931.         if (verbose_flag>1) fprintf(stderr, "%s chunk. size: %d\n", name, size);
  932.         if (strcmp(name, "NAME")==0) { get_name(sobj->name, (int)size, world);
  933.         } else if (strcmp(name, "STGF")==0) { sobj->stgf = get_UWORD(world);
  934.         } else if (strcmp(name, "OSZ2")==0) { process_OSZ2(sobj, world);
  935.         } else if (strcmp(name, "OSIZ")==0) { process_OSIZ(sobj, world);
  936.         } else if (strcmp(name, "POS2")==0) { process_POS2(sobj, world);
  937.         } else if (strcmp(name, "POSN")==0) { process_POSN(sobj, world);
  938.         } else if (strcmp(name, "ALN2")==0) { process_ALN2(sobj, world);
  939.         } else if (strcmp(name, "ALGN")==0) { process_ALGN(sobj, world);
  940.         } else if (strcmp(name, "PALN")==0) { process_PALN(sobj, world);
  941.         } else if (strcmp(name, "TALN")==0) { process_TALN(size, sobj, world);
  942.         } else if (strcmp(name, "ASSC")==0) { process_ASSC(size, sobj, world);
  943.         } else if (strcmp(name, "HING")==0) { process_HING(size, sobj, world);
  944.         } else if (strcmp(name, "LYR0")==0) { process_LYR0(sobj, world);
  945.         } else if (strcmp(name, "PTH2")==0) { process_PTH2(size, sobj, world);
  946.         } else if (strcmp(name, "GLB3")==0) { process_GLB3(size, sobj, world);
  947.         } else if (strcmp(name, "GLB2")==0) { process_GLB2(size, sobj, world);
  948.         } else if (strcmp(name, "AXIS")==0) { process_AXIS(sobj, world);
  949.         } else if (strcmp(name, "LIT2")==0) { process_LIT2(sobj, world);
  950.         } else if (strcmp(name, "LITE")==0) { process_LITE(sobj, world);
  951.         } else if (strcmp(name, "FIL3")==0) { process_FIL3(size, sobj, world);
  952.         } else if (strcmp(name, "FILE")==0) { process_FILE(size, sobj, world);
  953.         } else if (strcmp(name, "SPFX")==0) { process_SPFX(size, sobj, world, 0);
  954.         } else if (strcmp(name, "S2FX")==0) { process_SPFX(size, sobj, world, 2);
  955.         } else if (strcmp(name, "S3FX")==0) { process_SPFX(size, sobj, world, 3);
  956.         } else if (strcmp(name, "S4FX")==0) { process_SPFX(size, sobj, world, 4);
  957.         } else {
  958.             if (verbose_flag) output_warning(world, "SOBJ ", name, size);
  959.             else {
  960.                 for (i=size; i--; ) fgetc(world->inp);    /* Skip this section */
  961.             }
  962.         }
  963.         if (size&1) { fgetc(world->inp); len--; }    /* Skip odd byte */
  964.         len -= size;
  965.     }
  966. }
  967.  
  968. /* Chunks unique to Imagine 2.0 */
  969. static void process_OSIZ(sobj, world)
  970. SOBJ *sobj;
  971. WORLD *world;
  972. {
  973.     register OSIZ *osiz;
  974.  
  975.     if (!(osiz = (OSIZ*)malloc(sizeof(OSIZ)))) OUT_MEM("OSIZ");
  976.     bzero((char*)osiz, sizeof(OSIZ));
  977.     osiz->chunk_type = OSIZ_CHUNK;
  978.     osiz->flags = get_UWORD(world);
  979.     osiz->start = get_UWORD(world);
  980.     osiz->stop  = get_UWORD(world);
  981.     stuff_XYZ(&osiz->size, world);
  982.     insert_into_sorted_list((PALN**)&sobj->osiz, (PALN*)osiz);
  983. }
  984.  
  985. static void process_POSN(sobj, world)
  986. SOBJ *sobj;
  987. WORLD *world;
  988. {
  989.     register POSN *posn;
  990.  
  991.     if (!(posn = (POSN*)malloc(sizeof(POSN)))) OUT_MEM("POSN");
  992.     bzero((char*)posn, sizeof(POSN));
  993.     posn->chunk_type = POSN_CHUNK;
  994.     posn->flags = get_UWORD(world);
  995.     posn->start = get_UWORD(world);
  996.     posn->stop  = get_UWORD(world);
  997.     stuff_XYZ(&posn->posn, world);
  998.     insert_into_sorted_list((PALN**)&sobj->posn, (PALN*)posn);
  999. }
  1000.  
  1001. static void process_ALGN(sobj, world)
  1002. SOBJ *sobj;
  1003. WORLD *world;
  1004. {
  1005.     register ALGN *algn;
  1006.  
  1007.     if (!(algn = (ALGN*)malloc(sizeof(ALGN)))) OUT_MEM("ALGN");
  1008.     bzero((char*)algn, sizeof(ALGN));
  1009.     algn->chunk_type = ALGN_CHUNK;
  1010.     algn->flags = get_UWORD(world);
  1011.     algn->start = get_UWORD(world);
  1012.     algn->stop  = get_UWORD(world);
  1013.     stuff_XYZ(&algn->algn, world);
  1014.     insert_into_sorted_list((PALN**)&sobj->algn, (PALN*)algn);
  1015. }
  1016.  
  1017. static void process_HING(size, sobj, world)
  1018. ULONG size;
  1019. SOBJ *sobj;
  1020. WORLD *world;
  1021. {
  1022.     register HING *hing;
  1023.  
  1024.     if (!(hing = (HING*)malloc(sizeof(HING)))) OUT_MEM("HING");
  1025.     bzero((char*)hing, sizeof(HING));
  1026.     hing->chunk_type = HING_CHUNK;
  1027.     hing->flags = get_UWORD(world);
  1028.     hing->start = get_UWORD(world);
  1029.     hing->stop  = get_UWORD(world);
  1030.     size -= 7L;
  1031.     /* BCPL string... byte followed by string, followed by zero */
  1032.     get_UBYTE(world);
  1033.     if (size)
  1034.         get_name(hing->hingeobj, (int)size, world);
  1035.     insert_into_sorted_list((PALN**)&sobj->hing, (PALN*)hing);
  1036. }
  1037.  
  1038. static void process_GLB2(size, sobj, world)
  1039. ULONG size;
  1040. SOBJ *sobj;
  1041. WORLD *world;
  1042. {
  1043.     register GLB2 *glb2;
  1044.  
  1045.     if (!(glb2 = (GLB2*)malloc(sizeof(GLB2)))) OUT_MEM("GLB2");
  1046.     bzero((char*)glb2, sizeof(GLB2));
  1047.     glb2->chunk_type = GLB2_CHUNK;
  1048.     glb2->flags = get_UWORD(world);
  1049.     glb2->start = get_UWORD(world);
  1050.     glb2->stop  = get_UWORD(world);
  1051.     glb2->sky_blending = get_ULONG(world);
  1052.     glb2->starfield = get_FRACT(world);
  1053.     glb2->transition = get_ULONG(world);
  1054.     /* The following are FRACTional colors */
  1055.     stuff_XYZ(&glb2->ambient, world);
  1056.     stuff_XYZ(&glb2->horizon, world);
  1057.     stuff_XYZ(&glb2->zenith1, world);
  1058.     stuff_XYZ(&glb2->zenith2, world);
  1059.     stuff_XYZ(&glb2->fog_color, world);
  1060.     glb2->fog_bottom = get_FRACT(world);
  1061.     glb2->fog_top    = get_FRACT(world);
  1062.     glb2->fog_length = get_FRACT(world);
  1063.     glb2->brush_seq  = get_ULONG(world);
  1064.     glb2->backdrop_seq = get_ULONG(world);
  1065.     get_name(glb2->backdrop, 256, world);        /* Fixed size */
  1066.     size -= 355L;
  1067.     /* BCPL string... byte followed by string, followed by zero */
  1068.     get_UBYTE(world);
  1069.     if (size)
  1070.         get_name(glb2->globalbrush, (int)size, world);    /* Var. size */
  1071.     insert_into_sorted_list((PALN**)&sobj->glb2, (PALN*)glb2);
  1072. }
  1073.  
  1074. static void process_LITE(sobj, world)
  1075. SOBJ *sobj;
  1076. WORLD *world;
  1077. {
  1078.     register LITE *lite;
  1079.  
  1080.     if (!(lite = (LITE*)malloc(sizeof(LITE)))) OUT_MEM("LITE");
  1081.     bzero((char*)lite, sizeof(LITE));
  1082.     lite->chunk_type = LITE_CHUNK;
  1083.     lite->flags = get_UWORD(world);
  1084.     lite->start = get_UWORD(world);
  1085.     lite->stop  = get_UWORD(world);
  1086.     /* The following is a FRACTional color */
  1087.     stuff_XYZ(&lite->color, world);
  1088.     lite->transition = get_ULONG(world);
  1089.     insert_into_sorted_list((PALN**)&sobj->lite, (PALN*)lite);
  1090. }
  1091.  
  1092. static void process_FILE(size, sobj, world)
  1093. ULONG size;
  1094. SOBJ *sobj;
  1095. WORLD *world;
  1096. {
  1097.     register SFILE *file;
  1098.  
  1099.     if (!(file = (SFILE*)malloc(sizeof(SFILE)))) OUT_MEM("SFILE");
  1100.     bzero((char*)file, sizeof(SFILE));
  1101.     file->chunk_type = SFILE_CHUNK;
  1102.     file->flags = get_UWORD(world);
  1103.     file->start = get_UWORD(world);
  1104.     file->stop  = get_UWORD(world);
  1105.     file->cycles_to_perform = get_FRACT(world);
  1106.     file->initial_cycle_phase = get_FRACT(world);
  1107.     file->transition = get_ULONG(world);
  1108.     size -= 19L;
  1109.     /* BCPL string... byte followed by string, followed by zero */
  1110.     get_UBYTE(world);
  1111.     if (size)
  1112.         get_name(file->object_description, (int)size, world);
  1113.     insert_into_sorted_list((PALN**)&sobj->file, (PALN*)file);
  1114. }
  1115.  
  1116. /* Chunks unique to Imagine 3.0 or common to both */
  1117. static void process_OSZ2(sobj, world)
  1118. SOBJ *sobj;
  1119. WORLD *world;
  1120. {
  1121.     register OSZ2 *osz2;
  1122.  
  1123.     if (!(osz2 = (OSZ2*)malloc(sizeof(OSZ2)))) OUT_MEM("OSZ2");
  1124.     bzero((char*)osz2, sizeof(OSZ2));
  1125.     osz2->chunk_type = OSZ2_CHUNK;
  1126.     osz2->flags = get_UWORD(world);
  1127.     osz2->start = get_UWORD(world);
  1128.     osz2->stop  = get_UWORD(world);
  1129.     stuff_XYZ(&osz2->size, world);
  1130.     osz2->vel_0  = get_FRACT(world);
  1131.     osz2->vel_1  = get_FRACT(world);
  1132.     insert_into_sorted_list((PALN**)&sobj->osz2, (PALN*)osz2);
  1133. }
  1134.  
  1135. static void process_POS2(sobj, world)
  1136. SOBJ *sobj;
  1137. WORLD *world;
  1138. {
  1139.     register POS2 *pos2;
  1140.  
  1141.     if (!(pos2 = (POS2*)malloc(sizeof(POS2)))) OUT_MEM("POS2");
  1142.     bzero((char*)pos2, sizeof(POS2));
  1143.     pos2->chunk_type = POS2_CHUNK;
  1144.     pos2->flags = get_UWORD(world);
  1145.     pos2->start = get_UWORD(world);
  1146.     pos2->stop  = get_UWORD(world);
  1147.     stuff_XYZ(&pos2->pos2, world);
  1148.   pos2->vel_0 = get_FRACT(world);
  1149.   pos2->vel_1 = get_FRACT(world);
  1150.     insert_into_sorted_list((PALN**)&sobj->pos2, (PALN*)pos2);
  1151. }
  1152.  
  1153. static void process_ALN2(sobj, world)
  1154. SOBJ *sobj;
  1155. WORLD *world;
  1156. {
  1157.     register ALN2 *aln2;
  1158.  
  1159.     if (!(aln2 = (ALN2*)malloc(sizeof(ALN2)))) OUT_MEM("ALN2");
  1160.     bzero((char*)aln2, sizeof(ALN2));
  1161.     aln2->chunk_type = ALN2_CHUNK;
  1162.     aln2->flags = get_UWORD(world);
  1163.     aln2->start = get_UWORD(world);
  1164.     aln2->stop  = get_UWORD(world);
  1165.     stuff_XYZ(&aln2->aln2, world);
  1166.     aln2->vel_0  = get_FRACT(world);
  1167.     aln2->vel_1  = get_FRACT(world);
  1168.     insert_into_sorted_list((PALN**)&sobj->aln2, (PALN*)aln2);
  1169. }
  1170.  
  1171. static void process_PALN(sobj, world)
  1172. SOBJ *sobj;
  1173. WORLD *world;
  1174. {
  1175.     register PALN *paln;
  1176.  
  1177.     if (!(paln = (PALN*)malloc(sizeof(PALN)))) OUT_MEM("PALN");
  1178.     bzero((char*)paln, sizeof(PALN));
  1179.     paln->chunk_type = PALN_CHUNK;
  1180.     paln->flags = get_UWORD(world);
  1181.     paln->start = get_UWORD(world);
  1182.     paln->stop  = get_UWORD(world);
  1183.     insert_into_sorted_list(&sobj->aln2, paln);
  1184. }
  1185.  
  1186. static void process_TALN(size, sobj, world)
  1187. ULONG size;
  1188. SOBJ *sobj;
  1189. WORLD *world;
  1190. {
  1191.     register TALN *taln;
  1192.  
  1193.     if (!(taln = (TALN*)malloc(sizeof(TALN)))) OUT_MEM("TALN");
  1194.     bzero((char*)taln, sizeof(TALN));
  1195.     taln->chunk_type = TALN_CHUNK;
  1196.     taln->flags = get_UWORD(world);
  1197.     taln->start = get_UWORD(world);
  1198.     taln->stop  = get_UWORD(world);
  1199.     taln->initial_y = get_FRACT(world);
  1200.     taln->final_y   = get_FRACT(world);
  1201.     size -= 15L;
  1202.     /* BCPL string... byte followed by string, followed by zero */
  1203.     get_UBYTE(world);
  1204.     if (size)
  1205.         get_name(taln->trackobj, (int)size, world);
  1206.     insert_into_sorted_list((PALN**)&sobj->aln2, (PALN*)taln);
  1207. }
  1208.  
  1209. static void process_ASSC(size, sobj, world)
  1210. ULONG size;
  1211. SOBJ *sobj;
  1212. WORLD *world;
  1213. {
  1214.     register ASSC *assc;
  1215.  
  1216.     if (!(assc = (ASSC*)malloc(sizeof(ASSC)))) OUT_MEM("ASSC");
  1217.     bzero((char*)assc, sizeof(ASSC));
  1218.     assc->chunk_type = ASSC_CHUNK;
  1219.     assc->flags = get_UWORD(world);
  1220.     assc->start = get_UWORD(world);
  1221.     assc->stop  = get_UWORD(world);
  1222.     size -= 7L;
  1223.     /* string... byte followed by string, followed by zero pad if necessary */
  1224.     get_UBYTE(world);
  1225.     if (size)
  1226.         get_name(assc->assc_obj, (int)size, world);
  1227.     insert_into_sorted_list((PALN**)&sobj->assc, (PALN*)assc);
  1228. }
  1229.  
  1230. static void process_LYR0(sobj, world)
  1231. SOBJ *sobj;
  1232. WORLD *world;
  1233. {
  1234.     register LYR0 *lyr0;
  1235.  
  1236.     if (!(lyr0 = (LYR0*)malloc(sizeof(LYR0)))) OUT_MEM("LYR0");
  1237.     bzero((char*)lyr0, sizeof(LYR0));
  1238.     lyr0->chunk_type = LYR0_CHUNK;
  1239.     lyr0->layer = get_UWORD(world);
  1240.     insert_into_sorted_list((PALN**)&sobj->lyr0, (PALN*)lyr0);
  1241. }
  1242.  
  1243. static void process_PTH2(size, sobj, world)
  1244. ULONG size;
  1245. SOBJ *sobj;
  1246. WORLD *world;
  1247. {
  1248.     register PTH2 *pth2;
  1249.  
  1250.     if (!(pth2 = (PTH2*)malloc(sizeof(PTH2)))) OUT_MEM("PTH2");
  1251.     bzero((char*)pth2, sizeof(PTH2));
  1252.     pth2->chunk_type = PTH2_CHUNK;
  1253.     pth2->flags = get_UWORD(world);
  1254.     pth2->start = get_UWORD(world);
  1255.     pth2->stop  = get_UWORD(world);
  1256.     pth2->acceleration_frames = get_ULONG(world);
  1257.     pth2->start_speed = get_FRACT(world);
  1258.     pth2->deacceleration_frames = get_ULONG(world);
  1259.     pth2->end_speed = get_FRACT(world);
  1260.     size -= 23L;
  1261.     /* BCPL string... byte followed by string, followed by zero */
  1262.     get_UBYTE(world);
  1263.     if (size)
  1264.         get_name(pth2->path, (int)size, world);
  1265.     insert_into_sorted_list((PALN**)&sobj->pos2, (PALN*)pth2);
  1266. }
  1267.  
  1268. static void process_GLB3(size, sobj, world)
  1269. ULONG size;
  1270. SOBJ *sobj;
  1271. WORLD *world;
  1272. {
  1273.     register GLB3 *glb3;
  1274.  
  1275.     if (!(glb3 = (GLB3*)malloc(sizeof(GLB3)))) OUT_MEM("GLB3");
  1276.     bzero((char*)glb3, sizeof(GLB3));
  1277.     glb3->chunk_type = GLB3_CHUNK;
  1278.     glb3->flags = get_UWORD(world);
  1279.     glb3->start = get_UWORD(world);
  1280.     glb3->stop  = get_UWORD(world);
  1281.     glb3->brush_seq  = get_ULONG(world);
  1282.     glb3->starfield = get_FRACT(world);
  1283.     glb3->transition = get_ULONG(world);
  1284.     /* The following are FRACTional colors */
  1285.     stuff_XYZ(&glb3->ambient, world);
  1286.     stuff_XYZ(&glb3->horizon, world);
  1287.     stuff_XYZ(&glb3->zenith1, world);
  1288.     stuff_XYZ(&glb3->zenith2, world);
  1289.     stuff_XYZ(&glb3->fog_color, world);
  1290.     glb3->fog_bottom = get_FRACT(world);
  1291.     glb3->fog_top    = get_FRACT(world);
  1292.     glb3->fog_length = get_FRACT(world);
  1293.     glb3->backdrop_seq = get_ULONG(world);
  1294.     get_name(glb3->backdrop, 256, world);        /* Fixed size */
  1295.     size -= 351L;
  1296.     /* BCPL string... byte followed by string, followed by zero */
  1297.     get_UBYTE(world);
  1298.     if (size)
  1299.         get_name(glb3->globalbrush, (int)size, world);    /* Var. size */
  1300.     insert_into_sorted_list((PALN**)&sobj->glb3, (PALN*)glb3);
  1301. }
  1302.  
  1303. static void process_AXIS(sobj, world)
  1304. SOBJ *sobj;
  1305. WORLD *world;
  1306. {
  1307.     register SAXIS *axis;
  1308.  
  1309.     if (!(axis = (SAXIS*)malloc(sizeof(SAXIS)))) OUT_MEM("SAXIS");
  1310.     bzero((char*)axis, sizeof(SAXIS));
  1311.     axis->chunk_type = SAXIS_CHUNK;
  1312.     axis->flags = get_UWORD(world);
  1313.     axis->start = get_UWORD(world);
  1314.     axis->stop  = get_UWORD(world);
  1315.     insert_into_sorted_list((PALN**)&sobj->axis, (PALN*)axis);
  1316. }
  1317.  
  1318. static void process_LIT2(sobj, world)
  1319. SOBJ *sobj;
  1320. WORLD *world;
  1321. {
  1322.     register LIT2 *lit2;
  1323.  
  1324.     if (!(lit2 = (LIT2*)malloc(sizeof(LIT2)))) OUT_MEM("LIT2");
  1325.     bzero((char*)lit2, sizeof(LIT2));
  1326.     lit2->chunk_type = LIT2_CHUNK;
  1327.     lit2->flags = get_UWORD(world);
  1328.     lit2->start = get_UWORD(world);
  1329.     lit2->stop  = get_UWORD(world);
  1330.     /* The following is a FRACTional color */
  1331.     stuff_XYZ(&lit2->color, world);
  1332.     lit2->transition = get_ULONG(world);
  1333.     insert_into_sorted_list((PALN**)&sobj->lit2, (PALN*)lit2);
  1334. }
  1335.  
  1336. static void process_FIL3(size, sobj, world)
  1337. ULONG size;
  1338. SOBJ *sobj;
  1339. WORLD *world;
  1340. {
  1341.     register FIL3 *fil3;
  1342.  
  1343.     if (!(fil3 = (FIL3*)malloc(sizeof(FIL3)))) OUT_MEM("FIL3");
  1344.     bzero((char*)fil3, sizeof(FIL3));
  1345.     fil3->chunk_type = FIL3_CHUNK;
  1346.     fil3->flags = get_UWORD(world);
  1347.     fil3->start = get_UWORD(world);
  1348.     fil3->stop  = get_UWORD(world);
  1349.     fil3->cycles_to_perform = get_FRACT(world);
  1350.     fil3->initial_cycle_phase = get_FRACT(world);
  1351.     fil3->vel_0 = get_FRACT(world);
  1352.     fil3->vel_1 = get_FRACT(world);
  1353.     get_name(fil3->state, 18, world);        /* Fixed size */
  1354.     size -= 41L;
  1355.     /* BCPL string... byte followed by string, followed by zero */
  1356.     get_UBYTE(world);
  1357.     if (size)
  1358.         get_name(fil3->object_description, (int)size, world);
  1359.     insert_into_sorted_list((PALN**)&sobj->fil3, (PALN*)fil3);
  1360. }
  1361.  
  1362. static void process_SPFX (size, sobj, world, index)
  1363. ULONG size;
  1364. SOBJ *sobj;
  1365. WORLD *world;
  1366. int index;
  1367. {
  1368.     register SPFX *spfx;
  1369.     register ULONG len;
  1370.   UBYTE dummy;
  1371.  
  1372.     if (!(spfx = (SPFX*)malloc(sizeof(SPFX)))) OUT_MEM("SPFX");
  1373.     bzero((char*)spfx, sizeof(SPFX));
  1374.     spfx->chunk_type = SPFX_CHUNK; 
  1375.     spfx->flags = get_UWORD(world);
  1376.     spfx->start = get_UWORD(world);
  1377.     spfx->stop  = get_UWORD(world);
  1378.     size -= 7L;
  1379.     /* BCPL string... byte followed by string, followed by zero */
  1380.     len = get_UBYTE(world);
  1381.     get_name(spfx->effect, len, world);
  1382.     size -= (len + (len&1 ? 0 : 1));
  1383.  
  1384.   /* if the effect string was even, we need to grab and throw away the pad */
  1385.   if ( !(len & 1) ) dummy = get_UBYTE(world);
  1386.  
  1387.     /* get data and convert to uuencoded string */
  1388.     encode_data(spfx->effect_data, world->inp, size);
  1389.  
  1390.     /* need to know which SPFX it is in order to add it to the right list */
  1391.     switch (index) {
  1392.         case 0 :
  1393.             insert_into_sorted_list((PALN**)&sobj->spfx, (PALN*)spfx);
  1394.             break;
  1395.         case 2 :
  1396.             insert_into_sorted_list((PALN**)&sobj->s2fx, (PALN*)spfx);
  1397.             break;
  1398.         case 3 :
  1399.             insert_into_sorted_list((PALN**)&sobj->s3fx, (PALN*)spfx);
  1400.             break;
  1401.         case 4 :
  1402.             insert_into_sorted_list((PALN**)&sobj->s4fx, (PALN*)spfx);
  1403.     }
  1404. }
  1405.  
  1406. /* We use "PALN" here, even though this routine inserts all SOBJ sub-types
  1407.  * into their proper list, because all we need is "START" and "STOP"
  1408.  * information, and "PALN" is the minimal structure that provides this
  1409.  */
  1410. void insert_into_sorted_list(ppaln, paln)
  1411. PALN **ppaln, *paln;
  1412. {
  1413.     register PALN *p;
  1414.  
  1415.     if (!*ppaln) { *ppaln = paln; return; }        /* First in list */
  1416.     /* Now search through the list and insert in the proper place */
  1417.     for (p= *ppaln; p; p=p->next) {
  1418.         if (paln->start == p->start ||
  1419.             paln->start == p->stop  ||
  1420.             paln->stop  == p->start ||
  1421.             paln->stop  == p->stop) {
  1422.             fprintf(stderr, "WARNING!!! start and stop times collide! (%u-%u) vs (%u-%u)\n",
  1423.                 paln->start, paln->stop, p->start, p->stop);
  1424.         }
  1425.         if (paln->stop < p->start) {    /* Insert the item before this one */
  1426.             paln->prev = p->prev;
  1427.             paln->next = p;
  1428.             p->prev = paln;
  1429.             if (p == *ppaln) { *ppaln = paln; }    /* New head of list */
  1430.             return;
  1431.         }
  1432.         if (!p->next) {    /* Insert after this item */
  1433.             p->next = paln;
  1434.             paln->prev = p;
  1435.             return;
  1436.         }
  1437.     }
  1438.     /* Never will reach here! */
  1439. }
  1440.  
  1441. /* Find the last existing key frame that would be applicable for "frame" */
  1442. void delete_unused_frames(orig, frame)
  1443. PALN **orig;
  1444. {
  1445.     register PALN *p;
  1446.     PALN *p2;
  1447.  
  1448.     for (p= *orig; p; ) {
  1449.         if (frame>=p->start && frame<=p->stop) return;        /* It falls within this keyframe */
  1450.         if (frame>=p->stop && (!p->next || (p->next && frame<p->next->start))) return;        /* This is the one! */
  1451.         /* Otherwise, delete it */
  1452.         if (p->next) p->next->prev = p->prev;
  1453.         if (p->prev) p->prev->next = p->next;
  1454.         if (p== *orig) *orig = p->next;
  1455.         p2 = p->next;
  1456.         free(p);
  1457.         p = p2;
  1458.     }
  1459. }
  1460.  
  1461. static void mtrx_ident(mtrx)
  1462. register MTRX *mtrx;
  1463. {
  1464.     mtrx->tran.x  = mtrx->tran.y  = mtrx->tran.z  = 0.0;
  1465.     mtrx->scal.x  = mtrx->scal.y  = mtrx->scal.z  = 1.0;
  1466.     mtrx->rota1.y = mtrx->rota1.z = 0.0;
  1467.     mtrx->rota2.x = mtrx->rota2.z = 0.0;
  1468.     mtrx->rota3.x = mtrx->rota3.y = 0.0;
  1469.     mtrx->rota1.x = mtrx->rota2.y = mtrx->rota3.z = 1.0;
  1470. }
  1471.  
  1472. static void mmultiply(s, d)
  1473. register double *s;
  1474. register double *d;
  1475. {
  1476.     register int j;
  1477.     double tmp[9];
  1478.     tmp[0] = s[0]*d[0] + s[1]*d[3] + s[2]*d[6];
  1479.     tmp[1] = s[0]*d[1] + s[1]*d[4] + s[2]*d[7];
  1480.     tmp[2] = s[0]*d[2] + s[1]*d[5] + s[2]*d[8];
  1481.     tmp[3] = s[3]*d[0] + s[4]*d[3] + s[5]*d[6];
  1482.     tmp[4] = s[3]*d[1] + s[4]*d[4] + s[5]*d[7];
  1483.     tmp[5] = s[3]*d[2] + s[4]*d[5] + s[5]*d[8];
  1484.     tmp[6] = s[6]*d[0] + s[7]*d[3] + s[8]*d[6];
  1485.     tmp[7] = s[6]*d[1] + s[7]*d[4] + s[8]*d[7];
  1486.     tmp[8] = s[6]*d[2] + s[7]*d[5] + s[8]*d[8];
  1487.     for (j = 9; j--; ) d[j] = tmp[j];
  1488. }
  1489.  
  1490. /*
  1491. Matrix Inversion
  1492. by Richard Carling
  1493. from "Graphics Gems", Academic Press, 1990
  1494. tweaked heavily by Glenn M. Lewis to not require "GraphicsGems.h" and
  1495. to work only on 3x3 matrices
  1496. */
  1497.  
  1498.  
  1499. #define SMALL_NUMBER    1.e-8
  1500. #define det2x2(a,b,c,d)    ((a)*(d)-(b)*(c))
  1501. #define det3x3(a1, a2, a3, b1, b2, b3, c1, c2, c3)    \
  1502.     ((a1) * det2x2((b2), (b3), (c2), (c3))    \
  1503.     -(b1) * det2x2((a2), (a3), (c2), (c3))    \
  1504.     +(c1) * det2x2((a2), (a3), (b2), (b3)))
  1505.  
  1506. /* 
  1507.  *   inverse(original_matrix, inverse_matrix)
  1508.  * 
  1509.  *    calculate the inverse of a 3x3 matrix
  1510.  *
  1511.  *     -1     
  1512.  *     A  = ___1__ adjoint A
  1513.  *         det A
  1514.  */
  1515.  
  1516. void inverse(in, out)
  1517. register double *in, *out;
  1518. {
  1519.     int i;
  1520.     double det;
  1521.     void adjoint();
  1522.  
  1523.     /* calculate the adjoint matrix */
  1524.     adjoint(in, out);
  1525.     /*  calculate the 3x3 determinent
  1526.      *  if the determinent is zero, 
  1527.      *  then the inverse matrix is not unique.
  1528.      */
  1529.     det = det3x3(
  1530.         in[0], in[1], in[2],
  1531.         in[3], in[4], in[5],
  1532.         in[6], in[7], in[8]
  1533.     );
  1534.     if (fabs(det) < SMALL_NUMBER) return;    /* non-singular matrix */
  1535.     /* scale the adjoint matrix to get the inverse */
  1536.     det = 1.0/det;
  1537.     for (i=0; i<9; i++) out[i] *= det;
  1538. }
  1539.  
  1540. /* 
  1541.  *   adjoint(original_matrix, inverse_matrix)
  1542.  * 
  1543.  *     calculate the adjoint of a 4x4 matrix
  1544.  *
  1545.  *      Let  a   denote the minor determinant of matrix A obtained by
  1546.  *           ij
  1547.  *
  1548.  *      deleting the ith row and jth column from A.
  1549.  *
  1550.  *                    i+j
  1551.  *     Let  b   = (-1)    a
  1552.  *          ij            ji
  1553.  *
  1554.  *    The matrix B = (b  ) is the adjoint of A
  1555.  *                     ij
  1556.  */
  1557.  
  1558. void adjoint(in, out)
  1559. register double *in, *out;
  1560. {
  1561.     /* row column labeling reversed since we transpose rows & columns */
  1562.     out[0]  =   det2x2(in[4], in[7], in[5], in[8]);
  1563.     out[4]  = - det2x2(in[3], in[6], in[5], in[8]);
  1564.     out[6]  =   det2x2(in[3], in[6], in[4], in[7]);
  1565.  
  1566.     out[1]  = - det2x2(in[1], in[7], in[2], in[8]);
  1567.     out[4]  =   det2x2(in[0], in[6], in[2], in[8]);
  1568.     out[7]  = - det2x2(in[0], in[6], in[1], in[7]);
  1569.  
  1570.     out[2]  =   det2x2(in[1], in[4], in[2], in[5]);
  1571.     out[5]  = - det2x2(in[0], in[3], in[2], in[5]);
  1572.     out[8]  =   det2x2(in[0], in[3], in[1], in[4]);
  1573. }
  1574.  
  1575. OBJECT *load_staging_object(filename, mtrx)
  1576. char *filename;
  1577. MTRX *mtrx;
  1578. {
  1579.     WORLD *new;
  1580.     FILE *newinp;
  1581.     register OBJECT *p;
  1582.  
  1583.     /* Now, load in the external object */
  1584. TRY_EXTR_AGAIN:
  1585.     if (!(newinp=fopen(filename, "r"))) {
  1586.         fprintf(stderr, "Can't load in EXTR object: '%s'.\n",
  1587.             filename);
  1588.         fprintf(stderr, "Enter filneame (or CR to abort): "); fflush(stderr);
  1589.         fgets(filename, 512, stdin);
  1590.         if (!filename[0] || filename[0]=='\n') return(0L);
  1591.         goto TRY_EXTR_AGAIN;
  1592.     }
  1593.     new = read_World(newinp);
  1594.     fclose(newinp);
  1595.  
  1596.     /* scale, rotate, and translate new object hierarchy */
  1597.     /* First, take a look at the root object's size an orientation,
  1598.      * and scale all subobjects appropriately
  1599.      */
  1600.  
  1601.     p = new->object;
  1602.     if (p) {
  1603.         if (p->desc->size) {
  1604.             if (p->desc->size->x != 0.0)
  1605.                 mtrx->scal.x /= p->desc->size->x;
  1606.             if (p->desc->size->y != 0.0)
  1607.                 mtrx->scal.y /= p->desc->size->y;
  1608.             if (p->desc->size->z != 0.0)
  1609.                 mtrx->scal.z /= p->desc->size->z;
  1610.         }
  1611.         if (p->desc->axis) {
  1612. /*            inverse(&p->desc->axis->xaxi.x, &newmtrx.rota1.x);    */
  1613. /*            mmultiply(&newmtrx.rota1.x, &mtrx->rota1.x);            */
  1614.             mmultiply(&p->desc->axis->xaxi.x, &mtrx->rota1.x);
  1615.         }
  1616.     }
  1617.     for (p=new->object; p; p=p->next)
  1618.         move_extr(p, mtrx);
  1619.  
  1620.     p = new->object;
  1621.     free((char*)new);
  1622.     return(p);
  1623. }
  1624.  
  1625. void load_staging_frame_objects(world, frame)
  1626. WORLD *world;
  1627. int frame;
  1628. {
  1629.     register SOBJ *sobj;
  1630.     MTRX mtrx, tmpmtrx;
  1631.     OBJECT *obj;
  1632.     double angle;
  1633.  
  1634.     if (!world) return;
  1635.     if (!world->istg) return;
  1636.     if (frame<1 || frame>world->istg->maxf) {
  1637.         fprintf(stderr, "ERROR: desired frame (%d) is larger than MAXF (%d)\n",
  1638.             frame, world->istg->maxf);
  1639.         return;
  1640.     }
  1641.     /* Search through all of the "SOBJ" chunks and load in objects that
  1642.      * are active during the specified frame
  1643.      */
  1644.     for (sobj=world->istg->head; sobj; sobj=sobj->next) {
  1645.         /* Easiest method is to simply delete all the information in the SOBJ
  1646.          * sub-chunks that does not fall within the specified frame time.
  1647.          */
  1648.         delete_unused_frames((PALN**)&sobj->osz2, frame);        /* Size */
  1649.         delete_unused_frames((PALN**)&sobj->pos2, frame);        /* Position */
  1650.         delete_unused_frames((PALN**)&sobj->aln2, frame);        /* Alignment */
  1651.         delete_unused_frames((PALN**)&sobj->glb3, frame);        /* Globals */
  1652.         delete_unused_frames((PALN**)&sobj->axis, frame);        /* Stagefile AXIS */
  1653.         delete_unused_frames((PALN**)&sobj->lit2, frame);        /* Light */
  1654.         delete_unused_frames((PALN**)&sobj->fil3, frame);        /* Stage file */
  1655.  
  1656.         /* Now, we have a list of SOBJ chunks with information for this frame */
  1657.         if (!sobj->fil3) continue;    /* No filename information */
  1658.  
  1659.         /* Initialize transformation matrix structure */
  1660.         mtrx_ident(&mtrx);
  1661.  
  1662.         /* Now modify matrix based upon requested transformations */
  1663.         if (sobj->pos2) { bcopy((char*)&sobj->pos2->pos2.x, (char*)&mtrx.tran.x, sizeof(XYZ_st)); }
  1664.         if (sobj->osz2) { bcopy((char*)&sobj->osz2->size.x, (char*)&mtrx.scal.x, sizeof(XYZ_st)); }
  1665.         if (sobj->aln2) {
  1666.             /* First Z rotation, then X, then Y */
  1667.             if (sobj->aln2->aln2.z != 0.0) {
  1668.                 angle = sobj->aln2->aln2.z * PI / 180.0;
  1669.                 mtrx_ident(&tmpmtrx);    /* Initialize it */
  1670.                 tmpmtrx.rota1.x = tmpmtrx.rota2.y = cos(angle);
  1671.                 tmpmtrx.rota2.x = sin(angle);
  1672.                 tmpmtrx.rota1.y = -tmpmtrx.rota2.x;
  1673.                 mmultiply(&tmpmtrx.rota1.x, &mtrx.rota1.x);
  1674.             } else if (sobj->aln2->aln2.x != 0.0) {
  1675.                 angle = sobj->aln2->aln2.x * PI / 180.0;
  1676.                 mtrx_ident(&tmpmtrx);    /* Initialize it */
  1677.                 tmpmtrx.rota2.y = tmpmtrx.rota3.z = cos(angle);
  1678.                 tmpmtrx.rota3.y = sin(angle);
  1679.                 tmpmtrx.rota2.z = -tmpmtrx.rota3.y;
  1680.                 mmultiply(&tmpmtrx.rota1.x, &mtrx.rota1.x);
  1681.             } else if (sobj->aln2->aln2.y != 0.0) {
  1682.                 angle = sobj->aln2->aln2.y * PI / 180.0;
  1683.                 mtrx_ident(&tmpmtrx);    /* Initialize it */
  1684.                 tmpmtrx.rota1.x = tmpmtrx.rota3.z = cos(angle);
  1685.                 tmpmtrx.rota1.z = sin(angle);
  1686.                 tmpmtrx.rota3.x = -tmpmtrx.rota1.z;
  1687.                 mmultiply(&tmpmtrx.rota1.x, &mtrx.rota1.x);
  1688.             }
  1689.         }
  1690.         /* Okeydokey... let's load in that object! */
  1691.         obj = load_staging_object(sobj->fil3->object_description, &mtrx);
  1692.         if (world->curobj) {
  1693.             world->curobj->next = obj;
  1694.             obj->parent = world->curobj->parent;
  1695.             while (obj->next) {
  1696.                 obj->next->parent = obj->parent;
  1697.                 obj = obj->next;
  1698.                 world->curobj = obj;
  1699.             }
  1700.         } else {
  1701.             world->object = obj;
  1702.             obj->parent = 0;
  1703.         }
  1704.         world->curobj = obj;
  1705.     }
  1706. }
  1707.